<?php

namespace app\api\service;

use app\models\MerchantModel;
use think\Log;

error_reporting(E_ALL ^ E_NOTICE);

class SxfApiService extends PayService
{
    /**
     * 订单不存在或已失效.
     */
    const ORDER_NOT_EXISTS_ERROR = 4050102;
    /**
     * 订单已支付.
     */
    const ORDER_ALREADY_PAID_ERROR = 4050103;
    /**
     * 没有该商户信息.
     */
    const NO_MCH_INFO_ERROR = 4050104;
    /**
     * 调用微信支付失败.
     */
    const WEIXIN_PAY_FAIL_ERROR = 4050105;
    /**
     * 合作方私钥(替换成自己的).
     *
     * @var string
     */
    protected $privateKey;
    /**
     * 随行付公钥.
     *
     * @var mixed
     */
    protected $sxfpublic;
    /**
     * 支付配置.
     *
     * @var array
     */
    protected $payConfig = [];

    /**
     * 商户模型.
     *
     * @var MerchantModel
     */
    protected $merchantModel;

    public function __construct()
    {
        $this->returnData = [
            'code' => &$this->code,
            'message' => &$this->message,
            'data' => [],
        ];
        $this->merchantModel = new MerchantModel();
        $this->privateKey = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCBCyTqhWCe7zjZ4r0kEjn+/MgWUQ4CrhHcLn0CasnOvEwOi9iV
Vy+H/mDGUAKJT59czF1XJdMuptOWBK6fHZ5Em/lX8InQqyRyN/XPkZggRPe7/P2z
vjVWaIT4yzUWjIo0HlyVQQpBsYro0aT+snCsbMA66NfZg+BcSpcHNf0g9QIDAQAB
AoGAY6rx1lkx6U+nP1KK96NEPBeNiv8LrTI5BTC6yPUl7ZEtxUZp/96ZDZaBtGnz
q45d7dTCex7x32Rmo8X2AVtk80c/6wl57gTkkVW89FNaF7corKgSdHLom1xPMUr2
JS9tLL9/owAMAnGdoz2IKoxyjDq9/ZJCrdu67cP39gtNiDkCQQDbE7mqlA/QRXjh
DP6SV9gdc5vq6Xf97FtudFprGKLPlOsbRokjNTatS/CWxAXOMZkj0v+bJXVglR0h
mfVstlkjAkEAlsrXqzInBa9KczCAPM8KDVtXtZeYEEoKhNbx7zsW8gor9/KU6cFT
kr7RkyKOrmOBjUXBoRAvz55su9Gn6p4bBwJAKh2tqNxT+e8RIPq1if63Plo2VD/T
4I3qud5Gb6ZJzmxLkm/J92nIfCJIO0Ot9gjU7u0mVHYsDYg9FHObme2oTwI/HEXs
Ki09I9O6Id72LHClcduull3WJTe8wSuMMU7i/n7pv5O8WBfnk5wzr2LLXedKYzKx
G4HtdQA/YvfshBEhAkEArTdhImXcKnn+G2VTKvlnXiOwPBWYtYHq9Hnwe0rkjZLq
exR31BYOGCdbKVCAoyU6127Hc2HFXUHAQZ+bLkE4Ng==
-----END RSA PRIVATE KEY-----
EOD;
        $this->sxfpublic = <<<EOD
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjo1+KBcvwDSIo+nMYLeOJ19Ju4ii0xH66ZxFd869EWFWk/EJa3xIA2+4qGf/Ic7m7zi/NHuCnfUtUDmUdP0JfaZiYwn+1Ek7tYAOc1+1GxhzcexSJLyJlR2JLMfEM+rZooW4Ei7q3a8jdTWUNoak/bVPXnLEVLrbIguXABERQ0Ze0X9Fs0y/zkQFg8UjxUN88g2CRfMC6LldHm7UBo+d+WlpOYH7u0OTzoLLiP/04N1cfTgjjtqTBI7qkOGxYs6aBZHG1DJ6WdP+5w+ho91sBTVajsCxAaMoExWQM2ipf/1qGdsWmkZScPflBqg7m0olOD87ymAVP/3Tcbvi34bDfwIDAQAB
-----END PUBLIC KEY-----
EOD;
        $this->logType = 'sxf';
        $this->mapErrorMsg[self::ORDER_NOT_EXISTS_ERROR] = '订单不存在或已失效';
        $this->mapErrorMsg[self::NO_MCH_INFO_ERROR] = '没有该商户信息';
        $this->mapErrorMsg[self::WEIXIN_PAY_FAIL_ERROR] = '调用微信支付失败';
        parent::__construct();
    }

    /**
     * 执行随行付支付
     * User: wufeng
     * Date: 2019/4/9.
     *
     * @param $data
     *
     * @throws \think\exception\DbException
     *
     * @return bool|string
     */
    public function sxfPay($data)
    {
        $payType = '';
        if ('117' === $data['payment_method']) {
            $payType = 'WECHAT';
        } elseif ('118' === $data['payment_method']) {
            $payType = 'ALIPAY';
        } elseif ('120' === $data['payment_method']) {
			$payType = 'UNIONPAY';
		}

        $mch = $this->merchantModel->get($data['mch_id']);
		Log::record('商户信息='.json_encode($mch), 'pay');
        $payData['orgId'] = $mch['mch_appid']; //机构ID
        $payData['reqId'] = $data['receipt_number']; //订单号
        $payData['signType'] = 'RSA'; //签名类型
        $payData['timestamp'] = date('Ymdhis'); //请求时间：时间戳
        $payData['version'] = '1.0'; //版本
        //对应业务信息
        $payData['reqData'] = [
            'payType' => $payType, //支付类型：微信/WECHAT 支付宝/ALIPAY 云闪付/UNIONPAY
            'ordNo' => $data['receipt_number'], //商户订单号
            'subject' => $mch['mch_name'], //订单标题
            'amt' => $data['amount'], //金额
            'notifyUrl' => 'http://'.$_SERVER['HTTP_HOST'].'/api/Notify/sxfNotify', //回调地址
            'mno' => $mch['mch_number'], //商户入驻返回的商户编号
        ];
		Log::record('请求参数='.json_encode($payData), 'pay');
        $req = json_encode($payData);
        //提交服务器url
        $url = 'https://icm-management.suixingpay.com/management/qr/activeScan'; //正式地址
		return $this->sxf($req,$url);
    }

	/**
	 * 随行付
	 * User: wufeng
	 * Date: 2019/4/18
	 *
	 * @param $req
	 * @param $url
	 * @return bool|false|string
	 */
    public function sxf($req,$url)
	{
		$mygoods = json_decode($req, true);
		//排序
		$mygoods = $this->argSort($mygoods);
		//拼接
		$mystr = $this->createLinkstring($mygoods);
		//签名
		$sign = $this->rsaSign($mystr, $this->privateKey);
		$mygoods['sign'] = $sign;

		$datajsonstr = json_encode($mygoods, JSON_UNESCAPED_SLASHES);
		//对签名进行urlencode转码
		$curl = curl_init();
		$this_header = [
			'content-type: application/x-www-form-urlencoded; 
	charset=UTF-8',
		];
		curl_setopt($curl, CURLOPT_HTTPHEADER, $this_header);
		curl_setopt($curl, CURLOPT_URL, $url);
		curl_setopt($curl, CURLOPT_HEADER, 0);
		curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($curl, CURLOPT_POSTFIELDS, $datajsonstr);
		curl_setopt($curl, CURLOPT_HTTPHEADER, [
			'Content-Type: application/json',
			'Content-Length: '.\strlen($datajsonstr),
		]);
		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
		$tmpInfo = curl_exec($curl); //返回api的json对象
		//关闭URL请求
		curl_close($curl);
		$info = json_decode($tmpInfo, JSON_UNESCAPED_UNICODE);
		if($info['code'] != 'SXF0000'){
			return json_encode(['code' => $info['code'], 'msg' => $info['msg']]);
		}
		$newsign = $info['sign'];
		unset($info['sign']);
		ksort($info);
		$mystrs2 = $this->createLinkstring($info);
		//        		echo "返回拼装信息:$mystrs2<br>";
		//验证成功并返回数据
		if ($this->verify($mystrs2, $newsign, $this->sxfpublic)) {
			return $tmpInfo;
		}
	}

    /**
     * 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串.
     *
     * @param $para 需要拼接的数组
     *
     * @return string 拼接完成以后的字符串
     */
    public function createLinkstring($para)
    {
        $params = [];
        foreach ($para as $key => $value) {
            if (\is_array($value)) {
                $value = stripslashes(json_encode($value, JSON_UNESCAPED_UNICODE));
            }
            $params[] = $key.'='.$value;
        }

        return implode('&', $params);
    }

    /**
     * 对数组排序.
     *
     * @param $para 排序前的数组
     *
     * @return mixed 排序后的数组
     */
    public function argSort($para)
    {
        ksort($para);
        // reset($para);
        return $para;
    }

    /**
     * RSA签名.
     *
     * @param $data 待签名数据
     * @param $private_key_path 商户私钥文件路径
     *
     * @return string 签名结果
     */
    public function rsaSign($data, $private_key_path)
    {
        $res = openssl_get_privatekey($private_key_path);
        openssl_sign($data, $sign, $res);
        openssl_free_key($res);
        //base64编码
        return base64_encode($sign);
    }

    /**
     * RSA验签.
     *
     * @param $data
     * @param $sign
     * @param $pubKey
     *
     * @return bool
     */
    public function verify($data, $sign, $pubKey)
    {
        // $pubKey = file_get_contents('key/alipay_public_key.pem');
        //转换为openssl格式密钥
        $res = openssl_get_publickey($pubKey);
        //调用openssl内置方法验签，返回bool值
        $result = (bool) openssl_verify($data, base64_decode($sign, true), $res);
        //var_dump($result);
        //释放资源
        openssl_free_key($res);
        //返回资源是否成功
        return $result;
    }
}
